<?php
namespace app\index\controller;
// 命名空间
use app\common\controller\Frontend;

class Pay extends Frontend
{
    // 总结几点
    // 1、接口包中lib文件中的文件复制到Vendor后，重命名为TP规范的命名规则，为的是调用方便，当然你要改成其他名称也可以；
    // 2、把执行支付操作（doalipay），处理异步返回结果（notifyurl），处理跳转返回结果（returnurl）三个支付接口的核心页面写到一个PayAction控制器中。
    // 3、提交支付的页面中，可以在提交之前先把一些参数要传递的内容先通过隐藏域的方法组合好，比如金额先计算好，订单名称，订单描述等先用字符串组合好。然后提交表单，这样，在doalipay方法中只要直接构造传递参数，直接进行提交就行过了。
    // 4、支付返回后的处理因为要在异步和跳转两个方法中都要进行相应的判断和处理，所以，把这些判断和处理写到一个自定义函数中，这样只要调用函数即可，使得代码更加清晰明了。
    // 5、notify_url和return_url两种模式的返回url必须使用http://xxxxxxx这样的绝对路径，因为里是从支付宝平台返回到你的项目页面。不能使用相对路径。
    // 在类初始化方法中，引入相关类库
    // 页面跳转同步通知页面特性(return_url特性)
    // (1) 买家在支付成功后会看到一个支付宝提示交易成功的页面，该页面会停留几秒，然后会自动跳转回商户指定的同步通知页面（参数return_url）；
    // (2) 该页面中获得参数的方式，需要使用GET方式获取，如request.QueryString("out_trade_no")、$_GET['out_trade_no']；
    // // (3) 该方式仅仅在买家付款完成以后进行自动跳转，因此只会进行一次；
    // (4) 该方式不是支付宝主动去调用商户页面，而是支付宝的程序利用页面自动跳转的函数，使用户的当前页面自动跳转；
    // // (5) 基于(4)的原因，可在本机而不是只能在服务器上进行调试；
    // (6) 返回URL只有一分钟的有效期，超过一分钟该链接地址会失效，验证则会失败；
    // (7) 设置页面跳转同步通知页面（return_url）的路径时，不要在页面文件的后面再加上自定义参数。例如：
    // // 错误的写法：<http://www.alipay.com/alipay/return_url.php?xx=11>;
    // 正确的写法：<http://www.alipay.com/alipay/return_url.php>;
    // 服务器异步通知页面特性(notify_url特性)
    // (1) 必须保证服务器异步通知页面（notify_url）上无任何字符，如空格、HTML标签、开发系统自带抛出的异常提示信息等；
    // (2) 支付宝是用POST方式发送通知信息，因此该页面中获取参数的方式，如：
    // request.Form("out_trade_no")、$_POST['out_trade_no']。
    // (3) 支付宝主动发起通知，该方式才会被启用；
    // (4) 只有在支付宝的交易管理中存在该笔交易，且发生了交易状态的改变，支付宝才会通过该方式发起服务器通知（即时到账中交易状态为“等待买家付款”的状态默认是不会发送通知的）；
    // (5) 服务器间的交互，不像页面跳转同步通知可以在页面上显示出来，这种交互方式是不可见的；
    // (6) 第一次交易状态改变（即时到账中此时交易状态是交易完成）时，不仅页面跳转同步通知页面会启用，而且服务器异步通知页面也会收到支付宝发来的处理结果通知；
    // (7) 程序执行完后必须打印输出“success”（不包含引号）。如果商户反馈给支付宝的字符不是success这7个字符，支付宝服务器会不断重发通知，直到超过24小时22分钟。
    // 一般情况下，25小时以内完成8次通知（通知的间隔频率一般是：2m,10m,10m,1h,2h,6h,15h）；
    // (8) 程序执行完成后，该页面不能执行页面跳转。如果执行页面跳转，支付宝会收不到success字符，会被支付宝服务器判定为该页面程序运行出现异常，而重发处理结果通知；
    // (9) cookies、session等在此页面会失效，即无法获取这些数据；
    // (10) 该方式的调试与运行必须在服务器上，即互联网上能访问；
    // (11) 该方式的作用主要防止订单丢失，即页面跳转同步通知没有处理订单更新，它则去处理；
    // (12) 通知ID（参数notify_id）只有一分钟有效期，超过一分钟该次通知会验证失败。一旦验证成功下次再验证就会失效。
    public function _initialize()
    {
        vendor('Alipay.Corefunction');
        vendor('Alipay.Md5function');
        vendor('Alipay.Notify');
        vendor('Alipay.Submit');
    }

    public function payform(){
        //echo get_client_ip(); // 客户端的IP地址




        return $this->view->fetch();
    }
    // 执行支付操作
    public function doalipay()
    {
        $fee = $this->request->param('total_fee');
        if (! empty($fee) && $fee > 0) {
            $alipay_config = config('alipay_config');
//             dump($alipay_config);die;
            $alipay = config('alipay');
            /**
             * ************************请求参数*************************
             */
            // 需传入的参数
            $out_trade_no = "hs" . date("YmdHis"); // $_POST['trade_no'];//商户订单号 通过支付页面的表单进行传递，注意要唯一！
            $subject = '考试报名费'; // $_POST['ordsubject']; //订单名称 //必填 通过支付页面的表单进行传递
            $total_fee = $fee; // $_POST['ordtotal_fee']; //付款金额 //必填 通过支付页面的表单进行传递
            $body = '报名费缴纳'; // $_POST['ordbody']; //订单描述 通过支付页面的表单进行传递
            // $show_url ='https://www.so.com';// $_POST['ordshow_url']; //商品展示地址 通过支付页面的表单进行传递

            // 支付类型
            $payment_type = "1";
            // 必填，不能修改
            $notify_url = config('alipay.notify_url'); // 服务器异步通知页面路径
            $return_url = config('alipay.return_url'); // 页面跳转同步通知页面路径
            $seller_email = config('alipay.seller_email'); // 卖家支付宝帐户必填

            $anti_phishing_key = ""; // 防钓鱼时间戳 //若要使用请调用类文件submit中的query_timestamp函数
            $exter_invoke_ip = $_SERVER["REMOTE_ADDR"]; // 客户端的IP地址
            /**
             * *********************************************************
             */

            // 构造要请求的参数数组，无需改动
            $parameter = array(
                "service" => "create_direct_pay_by_user",
                "partner" => trim($alipay_config['partner']),
                "seller_email" => trim($alipay['seller_email']),
                "payment_type" => $payment_type,
                "notify_url" => $notify_url,
                "return_url" => $return_url,
                "out_trade_no" => $out_trade_no,
                "subject" => $subject,
                "total_fee" => $total_fee,
                "body" => $body,
                "show_url" => $show_url,
                "anti_phishing_key" => $anti_phishing_key,
                "exter_invoke_ip" => $exter_invoke_ip,
                "_input_charset" => trim(strtolower($alipay_config['input_charset']))
            );

            // 建立请求
            $alipaySubmit = new \AlipaySubmit($alipay_config);
            $html_text = $alipaySubmit->buildRequestForm($parameter, "get", "确认");
            echo $html_text;
        } else {
            $this->error("金额为空或小于等于零,请检查后，重新付款");
        }
    }
    // 处理异步返回结果
    public function notifyurl()
    {
        // 这里还是通过C函数来读取配置项，赋值给$alipay_config
        $alipay_config = config('alipay_config');

        // 计算得出通知验证结果
        $alipayNotify = new \AlipayNotify($alipay_config);
        $verify_result = $alipayNotify->verifyNotify();

        if ($verify_result) {

            // 验证成功
            // 获取支付宝的通知返回参数，可参考技术文档中服务器异步通知参数列表
            $out_trade_no = $_POST['out_trade_no']; // 商户订单号
            $trade_no = $_POST['trade_no']; // 支付宝交易号
            $trade_status = $_POST['trade_status']; // 交易状态
            $total_fee = $_POST['total_fee']; // 交易金额
            $notify_id = $_POST['notify_id']; // 通知校验ID。
            $notify_time = $_POST['notify_time']; // 通知的发送时间。格式为yyyy-MM-dd HH:mm:ss。
            $buyer_email = $_POST['buyer_email']; // 买家支付宝帐号；
            $parameter = array(
                "out_trade_no" => $out_trade_no, // 商户订单编号；
                "trade_no" => $trade_no, // 支付宝交易号；
                "total_fee" => $total_fee, // 交易金额；
                "trade_status" => $trade_status, // 交易状态
                "notify_id" => $notify_id, // 通知校验ID。
                "notify_time" => $notify_time, // 通知的发送时间。
                "buyer_email" => $buyer_email
            ) // 买家支付宝帐号；
            ;
            if ($_POST['trade_status'] == 'TRADE_FINISHED') {
                //
            } else
                if ($_POST['trade_status'] == 'TRADE_SUCCESS') {}
            echo "success"; // 请不要修改或删除
        } else {
            // 验证失败
            echo "fail";
        }
    }
    // 处理跳转返回结果
    public function returnurl()
    {
        // 这里还是通过C函数来读取配置项，赋值给$alipay_config
        $alipay_config = config('alipay_config');
        // 计算得出通知验证结果
        $alipayNotify = new \AlipayNotify($alipay_config);
        $verify_result = $alipayNotify->verifyReturn();
        if ($verify_result) {
            // 验证成功
            // 获取支付宝的通知返回参数，可参考技术文档中页面跳转同步通知参数列表
            $out_trade_no = $_GET['out_trade_no']; // 商户订单号
            $trade_no = $_GET['trade_no']; // 支付宝交易号
            $trade_status = $_GET['trade_status']; // 交易状态
            $total_fee = $_GET['total_fee']; // 交易金额
            $notify_id = $_GET['notify_id']; // 通知校验ID。
            $notify_time = $_GET['notify_time']; // 通知的发送时间。
            $buyer_email = $_GET['buyer_email']; // 买家支付宝帐号；

            $parameter = array(
                "out_trade_no" => $out_trade_no, // 商户订单编号；
                "trade_no" => $trade_no, // 支付宝交易号；
                "total_fee" => $total_fee, // 交易金额；
                "trade_status" => $trade_status, // 交易状态
                "notify_id" => $notify_id, // 通知校验ID。
                "notify_time" => $notify_time, // 通知的发送时间。
                "buyer_email" => $buyer_email
            ) // 买家支付宝帐号
            ;

            if ($_GET['trade_status'] == 'TRADE_FINISHED' || $_GET['trade_status'] == 'TRADE_SUCCESS') {
                echo "trade_status=" . $_GET['trade_status'];
                $this->redirect(config('alipay.successpage') . '?total_fee=' . $total_fee); // 跳转到配置项中配置的支付成功页面；
            } else {
                echo "trade_status=" . $_GET['trade_status'];
                $this->redirect(config('alipay.errorpage')); // 跳转到配置项中配置的支付失败页面；
            }
        } else {
            // 验证失败
            // 如要调试，请看alipay_notify.php页面的verifyReturn函数
            echo "支付失败！";
        }
    }
    public function change_status(){
        $total_fee = $this->request->param('total_fee');
        if (! empty($total_fee)) {
            $fa_income = M('fa_income');
            $data['income_amount'] = $total_fee;
            $data['income_time'] = date("Y-m-d H:i:s");
            $data['income_man'] = session('index_communist_no');
            $data['add_communist'] = session('index_communist_no');
            $data['status'] = 1;
            $data['add_time'] = date("Y-m-d H:i:s");
            $data['update_time'] = date("Y-m-d H:i:s");
            $flag = $fa_income->add($data);
            if ($flag) {
                $this->success("缴费成功", U('Cms/cms_communisthome_index'));
            }
        } else {
            $this->error("未缴费成功,请重新缴费！！！");
        }
    }

    /******报名支付流程*****************************************************************************/
    public function alipay(){
        $apply_id = $this->request->param('apply_id');
        $total_amount = $this->request->param('amount');
        $out_trade_no = getOrderNO($apply_id, $total_amount);
        $recruit_id = db('hs_recruit_apply')->where('apply_id',$apply_id)->value('recruit_id');
        $WIDbody    = db('hs_recruit')->where('recruit_id',$recruit_id)->value('recruit_title');//订单描述取会议名称
        $WIDsubject = $out_trade_no;      //订单名称
        alipay($out_trade_no,$WIDsubject,$total_amount,$WIDbody);//调用支付方法
        return $this->fetch();
    }

    /**
     * 功能：支付宝页面跳转同步通知页面
     * 版本：2.0
     * 修改日期：2018-08-07
     */
    public function return_url(){
        vendor('alipay.pagepay.service.AlipayTradeService');
        vendor('alipay.pagepay.buildermodel.AlipayTradePagePayContentBuilder');
        $config=config('alipay');

        $arr=$_GET;
        $alipaySevice = new \AlipayTradeService($config);
        $result = $alipaySevice->check($arr);

        if($result) {//验证成功
            //跳转到首页,并发送缴费成功通知.
            $out_trade_no = htmlspecialchars($_GET['out_trade_no']);//商户订单号
            //付款成功后填写发票信息
            $this->success('您已报名成功!',url('user/myapply'));
        }else {
            //验证失败
            echo "验证失败";
        }

    }
    /**
     * 功能：支付宝异步页面
     * 版本：2.0
     * 修改日期：2018-08-07
     */
    public function notify_url(){
        vendor('alipay.pagepay.service.AlipayTradeService');
        vendor('alipay.pagepay.buildermodel.AlipayTradePagePayContentBuilder');
        $config=config('alipay');

        $arr=$_POST;
        $alipaySevice = new \AlipayTradeService($config);
        $alipaySevice->writeLog(var_export($_POST,true));
        $result = $alipaySevice->check($arr);

        if($result) {//验证成功
            $out_trade_no = $_POST['out_trade_no'];//商户订单号
            $trade_status = $_POST['trade_status'];//交易状态
            $trade_no     = $_POST['trade_no'];//支付宝交易号
            if($_POST['trade_status'] == 'TRADE_FINISHED') {
                //判断该笔订单是否在商户网站中已经做过处理
                //如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
                //请务必判断请求时的total_amount与通知时获取的total_fee为一致的
                //如果有做过处理，不执行商户的业务程序
            }else if ($_POST['trade_status'] == 'TRADE_SUCCESS') {
                handleOrder($out_trade_no,'paid');//1、更改订单状态
                handleApply($out_trade_no);//2、更改报名状态
            }
        }else {
            //验证失败
            echo "fail";
        }
    }
    /******报名支付流程结束*****************************************************************************/
}

